package concurrentpractice;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import lombok.Data;
import lombok.experimental.Accessors;
import org.junit.Test;

/**
 * 之前两个解法是直接用的 Thread，这个加上 ThreadPool + Runnable
 */
public class VolatileSolution {

  private enum Printer {
    NUMBER, LETTER
  }

  @Data
  @Accessors(chain = true)
  private class Scheduler {

    private Printer enabledPrinter = Printer.NUMBER;
  }

  private volatile Scheduler scheduler = new Scheduler();

  @Test
  public void verifyVolatile() throws ExecutionException, InterruptedException {
    Runnable numberPrint = () -> {
      {
        for (int i = 1; i < 52; i = i + 2) {
          while (scheduler.getEnabledPrinter() != Printer.NUMBER) {
            // waiting for numberPrinter be enabled.
          }
          for (int j = 0; j < 2; j++) {
            System.out.print(i + j);
          }
          scheduler.setEnabledPrinter(Printer.LETTER);
        }
      }
    };
    Runnable letterPrint = () -> {
      for (char i = 'A'; i <= 'Z'; i++) {

        while (scheduler.getEnabledPrinter() != Printer.LETTER) {
          // waiting for letterPrinter be enabled.
        }
        System.out.print(i);
        scheduler.setEnabledPrinter(Printer.NUMBER);
      }
    };

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
    Future numberPrintFuture = fixedThreadPool.submit(numberPrint);
    Future letterPrintFuture = fixedThreadPool.submit(letterPrint);

    fixedThreadPool.shutdown();

    numberPrintFuture.get(); // waiting for numberPrint done.
    letterPrintFuture.get(); // waiting for letterPrint done.
  }
}
